iT邦幫忙

2023 iThome 鐵人賽

DAY 14
0
AI & Data

從Keras框架與數學概念了解機器學習系列 第 14

[從Keras框架與數學概念了解機器學習] - 14. 自定義 initializers

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20230914/20144614ScbKmVxGYe.jpg

這節會觀察自己定義 initializer。 我們可以使用一個 subClass 來定義一個initializer,前提是這個自定義的 initializer 類別是 callable,也就是類別要實作 call 函式。我們可以沿用上一節的範例,來加入自定義的initializer來觀察。

範例如下:

import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras import layers
from tensorflow.keras.models import Model
from tensorflow.keras.datasets import mnist
from tensorflow.keras.initializers import Initializer
import keras.optimizers as optimizers

(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype("float32") / 255
test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype("float32") / 255

class ExampleRandomNormal(Initializer):

    def __init__(self, mean, stddev):
        self.mean = mean
        self.stddev = stddev
    
    def __call__(self, shape, dtype=None):
        return tf.random.normal(shape, mean=self.mean, stddev=self.stddev, dtype=dtype)

    def get_config(self): # To support serialization
        return {'mean': self.mean, 'stddev': self.stddev}
        

class SimpleDense(layers.Layer):

    def __init__(self, units=32):
        super(SimpleDense, self).__init__()
        self.units = units
        
    def build(self, input_shape):
        self.w = self.add_weight(shape=(input_shape[-1], self.units),
                        initializer= ExampleRandomNormal( mean=0.0 , stddev=0.05 ),
                        trainable=True)
        self.b = self.add_weight(shape=(self.units,),
                                initializer='random_normal',
                                trainable=True)
    def call(self, inputs):
        return tf.matmul(inputs, self.w) + self.b
        
model = Sequential([
SimpleDense(512),
layers.Dense(10, activation="softmax")
])


model.compile(optimizer= 
    optimizers.get( {"class_name": "rmsprop", "config": {"learning_rate" : 0.001} } ) ,
    loss="sparse_categorical_crossentropy",
    metrics=["accuracy"])
    
model.fit(train_images, train_labels, epochs=1, batch_size=128)

https://ithelp.ithome.com.tw/upload/images/20230914/2014461468sa9lr3Ko.jpg

上圖是模型在做build時,針對 initializer 的運作內容做展示。紫色框框就是自定義 initializer 運作過程。自定義initializer類別繼承keras.initializers.Initializer類別。

當使用自定義initializer的Layer正在build時,其中針對initializer設定時會叫用keras.engine.base_layer.Layer.add_weight,進而執行 keras.initializers.get 來設定 Layer 的 initializer屬性。

接下來要準備產生權重張量時,呼叫keras.engine.base_layer_utils.make_variable,針對initializer的使用,這時就會繼續呼叫 ExampleRandomNormal.call。 當keras.engine.base_layer_utils.make_variable產生好權重張量時,回傳給SimpleDense.build函式,供SimpleDense設定權重屬性。接著再繼續執行下一個連接的Layer的build運作。

所以由圖可以觀察到,自定義initializer勢必要將自身的__call__時做出來,這樣才可以讓keras.initializers.get順利偵測出此initializer實體是callable,讓build的運作可以繼續下去。然後這個__call__函式還要跟keras.initializers.Initializer父類別之__call__函式一樣,都要傳入shape。

以上是自定義initializer之運作與要注意的事項。


上一篇
[從Keras框架與數學概念了解機器學習] - 13. 自訂義 Layer
下一篇
[從Keras框架與數學概念了解機器學習] - 15. optimizer 與 learning_rate
系列文
從Keras框架與數學概念了解機器學習30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言